package com.bkhech.spring.security.example.controller;

import com.bkhech.spring.security.example.authority.SecurityFrameworkService;
import com.bkhech.spring.security.example.domain.CommonResult;
import com.bkhech.spring.security.example.domain.LoginUser;
import com.bkhech.spring.security.example.service.UserService;
import com.bkhech.spring.security.example.util.SecurityFrameworkUtils;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.expression.DenyAllPermissionEvaluator;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author guowm
 * @date 2023/1/10
 */
@RequiredArgsConstructor
@RestController
public class UserController {

    final UserService userService;

    /**
     * 使用 spring security 内置的权限功能
     *
     * 1. hasRole() 如果没有前缀 ROLE_ ，则自动加上
     * 2. hasAuthority() 则不会
     * 3. hasPermission(Object target, Object permission)
     *      Spring Security 默认没有实现，全部没有权限 {@link DenyAllPermissionEvaluator}
     *      例如：hasPermission(#loginUser, 'ROLE_admin'), 注意：#loginUser 加上 '' 表示自定传， 不加表示引用当前对象
     *
     * @see SecurityExpressionRoot
     * @see ExpressionBasedPreInvocationAdvice
     */
    @PreAuthorize("hasRole('admin')")
//    @PreAuthorize("hasAuthority('ROLE_admin')")
//    @PreAuthorize("hasPermission(#loginUser, 'ROLE_admin')")
    @GetMapping("/info")
    @ApiOperation("获取用户信息")
    public CommonResult<LoginUser> userInfo(LoginUser loginUser) {
        return CommonResult.success(SecurityFrameworkUtils.getLoginUser());
    }

    /**
     * 使用自定义的权限框架功能
     *
     * @see SecurityFrameworkService
     */
    @PreAuthorize("@ss.hasRole('common_user')")
    @GetMapping("/info2")
    @ApiOperation("获取用户信息2")
    public CommonResult<LoginUser> userInfo2() {
        return CommonResult.success(SecurityFrameworkUtils.getLoginUser());
    }


}
